package com.neusoft.elm.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {
	private static final String URL = "jdbc:mysql://localhost:3306/elm?characterEncoding=utf-8";
	private static final String DRIVER = "com.mysql.jdbc.Driver";
	private static final String USERNAME = "root";//用户名
	private static final String PASSWORD = "123456";//密码
	
	private static final ThreadLocal<Connection> TL = new ThreadLocal<>();
	/*
	使用ThreadLocal实现了线程级别的数据库连接管理。ThreadLocal是一个线程本地变量
	，每个线程都有自己独立的副本，可以保证每个线程使用独立的数据库连接。
	 */
	private static Connection createConnection() {
		/*
		createConnection()方法用于创建数据库连接
		。首先加载数据库驱动程序，然后通过DriverManager.getConnection()方法获取连接。
		 */
		Connection con = null;//确保只有连接对象为空时才建立新的链接
		if(con == null) {
			try {
				Class.forName(DRIVER);
				/*
				使用 Class.forName(DRIVER) 加载数据库驱动程序。这里的 DRIVER 是一个常量，表示数据库驱动程序的名称或类的完全限定名。
				Class.forName(String className)：加载指定名称的类。在这里，它用于加载数据库驱动程序的类。
				 */
				con = DriverManager.getConnection(URL,USERNAME,PASSWORD);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return con;
	}
	
	//公开一个接口，让外界获得一个connection对象
	public static Connection getConnection() {
		Connection con = null;
		con = TL.get();
		if(con == null) {
			con = createConnection();
			TL.set(con);//TL.set(Object value)：将值存储到线程局部变量中。在这里，它用于将连接对象保存到线程局部变量中
		}
		return con;
	}
	/*
	。它首先从ThreadLocal中获取连接，如果连接不存在，则调用createConnection()方法创建一个新的连接，并将其存储到ThreadLocal中。
	通过使用线程局部变量，该代码可以确保每个线程都可以获取到自己的数据库连接，并且在同一个线程内部可以复用连接对象，从而提高连接的效率和性能。
	 */
	
	//开启一个事务
	public static void beginTransaction() throws Exception{
		Connection con = null;
		con = TL.get();
		if(con == null) {
			con = createConnection();
			TL.set(con);
		}
		//开启一个事务,开启后调用dao层
		con.setAutoCommit(false);
	}
	/*
	方法用于开启事务。它获取数据库连接，并将其设置为手动提交模式（即关闭自动提交），从而开启一个新的事务。
	 */
	//提交一个事务
	public static void commitTransaction() throws Exception{
		Connection con = TL.get(); //已经处在一个事务当中，那肯定有一个connection啊 
		con.commit();
	}
	
	//如果事务异常，那么就需要回滚事务
	public static void rollbackTransaction() throws Exception{
		Connection con = TL.get();
		con.rollback();
	}
	
	//关闭资源
	public static void close(ResultSet rs,PreparedStatement pst) {
		try {
			if(rs != null) {
				rs.close();
			}
			if(pst != null) {
				pst.close();
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public static void close(PreparedStatement pst) {
		try {
			if(pst != null) {
				pst.close();
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public static void close() {
		Connection con = TL.get();
		try {
			if(con != null) {
				con.close();
			}
			TL.remove();
			//必须要remove，不然容易造成内存泄漏
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
